package com.gitee.loyo;

import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.JsonObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.gitee.loyo.Const.WEBSOCKET_CLIENT_HEADER;

@Slf4j
@Configuration
@ComponentScan
@EnableConfigurationProperties({ApiBridgeConfig.class})
@RequiredArgsConstructor
public class ApiBridgeAutoConfiguration {
    final ApiBridgeConfig bridgeConfig;
    final Vertx vertx = Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1).setBlockedThreadCheckIntervalUnit(TimeUnit.DAYS));
    @Value("${server.port:80}") int port;
    @Value("${spring.application.name:}") String appName;


    @PostConstruct
    public void onStartup() {
        if(!bridgeConfig.isEnable()){
            return;
        }
        if(bridgeConfig.getClient().getName() == null || bridgeConfig.getClient().getName().isEmpty()){
            if(appName.isEmpty()){
                appName = "SpringApplication";
            }

            bridgeConfig.getClient().setName(appName + "@" + getComputerName());
        }
        Objects.requireNonNull(bridgeConfig.getClient().getName(), "required property 'bridge.client.name' is missing");
        Objects.requireNonNull(bridgeConfig.getRemote().getHost(), "required property 'bridge.remote.host' is missing");

        JsonObject config = new JsonObject().put(
            "defaultHost", bridgeConfig.getRemote().getHost()
        ).put(
            "defaultPort", bridgeConfig.getRemote().getPort()
        ).put(
            "bridge",
            new JsonObject().put(
                "client",
                new JsonObject().put(
                    "headers",
                    new JsonObject().put(
                        WEBSOCKET_CLIENT_HEADER, bridgeConfig.getClient().getName()
                    )
                )
            ).put(
                "proxy",
                new JsonObject().put(
                    "defaultHost", "localhost"
                ).put(
                    "defaultPort", port
                )
            )
        );
        vertx.deployVerticle(new BridgeClient(config), new DeploymentOptions().setConfig(config)).onComplete(ar -> {
            if(ar.failed()){
                ar.cause().printStackTrace();
                vertx.close();
                System.exit(0);
            }
        });
    }

    @PreDestroy
    public void onDestroy() {
        vertx.close();
    }


    private String getComputerName(){
        String name = System.getProperty("user.name", "");
        if(!name.isEmpty())
            return name;
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))){
            return reader.readLine();
        }catch (Exception e){
            return "";
        }
    }
}
